package main

import (
	"context"
	"distributed-cache/bufferpoll"
	"distributed-cache/controller"
	"distributed-cache/superconfig"
	"fmt"
	"github.com/samuel/go-zookeeper/zk"
	"log"
	"net/http"
)

var ctx = context.Background()
var virtualPool *bufferpoll.VirtualPool

func watchDataByPath(conn *zk.Conn, nodePath string) (chan []byte, chan error) {
	snapshots := make(chan []byte)
	errors := make(chan error)
	go func() {
		for {
			data, _, events, err := conn.GetW(nodePath)
			if err != nil {
				errors <- err
			}
			snapshots <- data
			select {
			case evt := <-events:
				if evt.Err != nil {
					errors <- evt.Err
					return
				}
				fmt.Printf("GetW Event Path:%v, Type:%v\n", evt.Path, evt.Type)
			}
		}
	}()
	return snapshots, errors
}

func PutHandler(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	key := query["key"][0]
	value := query["value"][0]
	controller.Put(ctx, virtualPool, key, value)
	fmt.Fprintln(w, "{\"message\":\"success\"}")
}

func GetHandler(w http.ResponseWriter, r *http.Request) {
	query := r.URL.Query()
	key := query["key"][0]
	result := controller.Get(ctx, virtualPool, key)
	_, err := fmt.Fprintln(w, result)
	if err != nil {
		log.Fatal("响应内容出错")
	}
}

func init() {
	zkClient := superconfig.SetUp()
	date, _ := zkClient.Get("/test")
	redisConfigList, _ := superconfig.ParseToRedisConfig(date)
	fmt.Println(len(redisConfigList))

	redisPool := bufferpoll.RedisPool{}
	if len(redisConfigList) == 0 {
		fmt.Println("Must have at least one redis ")
		return
	}
	redisPool.Init(ctx, redisConfigList)
	// 监听zk变动
	dataChan, dataErrChan := watchDataByPath(zkClient.ZkConn, "/test")
	go func() {
		for {
			select {
			case changeErr := <-dataErrChan:
				fmt.Println("content change occur err, info: ", changeErr)
			case changedData := <-dataChan:
				fmt.Println("WatchGetData changed, info: ", string(changedData))
				configRedisList, err := superconfig.ParseToRedisConfig(changedData)
				if err == nil {
					redisPool.AddNewRedisList(ctx, configRedisList)
				}
			}
		}
	}()
	virtualPool = bufferpoll.GetVirtualPool(ctx)
}

func main() {
	//input := bufio.NewScanner(os.Stdin)
	//
	//go func() {
	//	for true {
	//		input.Scan()
	//		array := strings.Split(strings.TrimSpace(input.Text()), " ")
	//		if len(array) == 1 {
	//			fmt.Println("exit")
	//			break
	//		}
	//		start := time.Now()
	//		hashValue := percolator.StringToHash(array[1])
	//		if array[0] == "set" {
	//			if len(array) < 3 {
	//				continue
	//			}
	//			go bufferpoll.SetOperation(ctx, hashValue%1024, strings.Join([]string{array[1], array[2]}, ":"), virtualPool)
	//		} else if array[0] == "get" {
	//			if bs.Has(percolator.StringToHash(array[1])) {
	//				value := bufferpoll.GetResult(ctx, hashValue%1024, array[1], virtualPool)
	//				fmt.Printf("value: %s \n", value)
	//			} else {
	//				fmt.Printf("not exist value of this key: %s\n", array[1])
	//			}
	//		}
	//		fmt.Printf("spend time is %v\n", time.Since(start))
	//	}
	//}()

	http.HandleFunc("/put", PutHandler)
	http.HandleFunc("/get", GetHandler)
	err := http.ListenAndServe(":8000", nil)
	if err != nil {
		fmt.Println("serve error")
	}
}
